/*** Sección de declaraciones ***/

%{
/* Código en C que será copiado */
#include <stdio.h>



#define CIRCLE 	01
#define BOX 2
#define MOVE 3
#define SCALE 4
#define ROTATE 05
#define REPEAT 06
#define DEFINE 07 
#define DEFINE_USE 8
#define PARENTESIS_A 9
#define PARENTESIS_C 10



typedef struct{
	int entera;
	int decimal;
	char signo;
	
}numero;




//Nodo que va ser de backbone de el "arbol"
typedef struct nodo_generico{
	int tipo;
	void * nodo;
	struct nodo_generico * sig;
	struct nodo_generico * ant;
	struct nodo_generico * adentro;
} nodo_generico;



///VARIABLES GLOBALES

//Primer nodo
nodo_generico *primero;

//Ultimo nodo
nodo_generico *ultimo;

//Determina si hubo error, osea se leyo algo que no iba
char error;

//Variable que determina si debe ir otro grafo despues del ultimo que lei
//es decir, si leo circle 4, vale false, si leo rotate 4 vale true
char falta_g;

int parentesis;



typedef struct nodo_circle{
	numero r;
}nodo_circle;




typedef struct nodo_box{
	numero ancho;
	numero alto;
}nodo_box;


typedef struct nodo_move{
	numero dx;
	numero dy;
	nodo_generico g;
}nodo_move;


typedef struct nodo_scale{
	numero fx;
	numero fy;
	nodo_generico g;
}nodo_scale;

typedef struct nodo_rotate{
	int a;
	nodo_generico g;
}nodo_rotate;

typedef struct nodo_repeat{
	int n;
	numero dx;
	numero dy;
	nodo_generico g;
}nodo_repeat;

typedef struct nodo_define{
	char *nombre;
	nodo_generico g;
}nodo_define;

typedef struct nodo_define_use{
	char *nombre;
}nodo_define_use;

//Setea un numero
void setNumero(numero * num, int entera, int decimal, char signo){
	num->entera=entera;
	num->decimal=decimal;
	num->signo=signo;
}

//Crea nodo generico
//y le asigna tipo y nodo 
nodo_generico * crearNodoGenerico(int tipo, void * nodo_nuevo){
		   nodo_generico * nodo_g_nuevo = malloc(sizeof(nodo_generico));
           nodo_g_nuevo->tipo = tipo;
           nodo_g_nuevo->sig = NULL;
           
           //Le enlazo el nodo correcto
           nodo_g_nuevo->nodo = nodo_nuevo;
           
           //Lo asigno como sig del ultimo nodo
           ultimo->sig= nodo_g_nuevo;
           
           //Arreglo el ultimo
           ultimo=nodo_g_nuevo;
		
			return nodo_g_nuevo;
}

//funcion que imprimi numero
void imprimiNumero(numero n){
		if(n.signo==0)	printf("%d.%d ",n.entera,n.decimal);
		else 	printf("-%d.%d ",n.entera,n.decimal);
}





//funcione que imprime el resultado
int imprimir(nodo_generico * nodo){
	//Si estoy en el primer caso, el primer nodo siempre es vacio
	if(nodo == primero){
		if(nodo->sig){
			imprimir(nodo->sig);
			return 0;
		}
	}
	
	//Si no es el primer nodo, imprimo su asociado
	
	//Tipo BOX
	if(nodo->tipo==BOX){
		nodo_box * nodo_particular = ( nodo_box *)  nodo->nodo;
		printf("box ");
		imprimiNumero(nodo_particular->ancho);
		imprimiNumero(nodo_particular->alto);
		printf("\n");
		 
		if (nodo->sig) 	imprimir(nodo->sig);
		return 0;
	}
	
	//tipo CIRCLE
	if(nodo->tipo==CIRCLE){
		nodo_circle * nodo_particular = ( nodo_circle *)  nodo->nodo;
		printf("circle ");
		imprimiNumero(nodo_particular->r);
		printf("\n");
		if (nodo->sig) 	imprimir(nodo->sig);
		return 0;
	}
	
	//tipo move
	if(nodo->tipo==MOVE){
		nodo_move * nodo_particular = ( nodo_move *)  nodo->nodo;
		printf("move ");
		imprimiNumero(nodo_particular->dx);
		imprimiNumero(nodo_particular->dy);
		printf("\n");
		if (nodo->sig) 	imprimir(nodo->sig);
		return 0;
	}
	
	//tipo SCALE
	if(nodo->tipo==SCALE){
		nodo_scale * nodo_particular = ( nodo_scale *)  nodo->nodo;
		printf("scale ");
		imprimiNumero(nodo_particular->fx);
		imprimiNumero(nodo_particular->fy);
		printf("\n");
		if (nodo->sig) 	imprimir(nodo->sig);
		return 0;
	}
	
	//tipo rotate
	if(nodo->tipo==ROTATE){
		nodo_rotate * nodo_particular = ( nodo_rotate *)  nodo->nodo;
		printf("rotate ");
		printf("%d", nodo_particular->a);
		printf("\n");
		if (nodo->sig) 	imprimir(nodo->sig);
		return 0;
	}
	
	
	//tipo repeat
	if(nodo->tipo==REPEAT){
		nodo_repeat * nodo_particular = ( nodo_repeat *)  nodo->nodo;
		printf("repeat ");
		printf("%d", nodo_particular->n);
		imprimiNumero(nodo_particular->dx);
		imprimiNumero(nodo_particular->dy);
		printf("\n");
		if (nodo->sig) 	imprimir(nodo->sig);
		return 0;
	}
	
	if(nodo->tipo== PARENTESIS_A ){
		printf(" ( \n");
		if (nodo->sig) 	imprimir(nodo->sig);
		return 0;
	}
	if(nodo->tipo==PARENTESIS_C){
		printf(" ) \n");
		if (nodo->sig) 	imprimir(nodo->sig);
		return 0;
	}
	
	
}


void f_move(int par1_e, int par1_d, char par1_s, int par2_e, int par2_d, char par2_s ){
	 nodo_move * nodo_nuevo = malloc(sizeof(nodo_move));
           
           ///TODO: Levantar los numeros
           //puse 1 por poner alguno
           setNumero(& nodo_nuevo->dx,par1_e,par1_d,par1_s);
           setNumero(& nodo_nuevo->dy,par2_e,par2_d,par2_s);
                      
           //Creo el nodo generico
           crearNodoGenerico( MOVE , nodo_nuevo);
     
}

void f_scale(int par1_e, int par1_d, char par1_s, int par2_e, int par2_d, char par2_s ){
	  nodo_scale * nodo_nuevo = malloc(sizeof(nodo_scale));
           
           ///TODO: Levantar los numeros
           //puse 1 por poner alguno
           setNumero(& nodo_nuevo->fx,par1_e,par1_d,par1_s);
           setNumero(& nodo_nuevo->fy,par2_e,par2_d,par2_s);
                      
           //Creo el nodo generico
           crearNodoGenerico( SCALE , nodo_nuevo);
           
           //Falta grafico, pues es recursivo
           falta_g=1;
}

void f_rotate(int angulo){
			   nodo_rotate * nodo_nuevo = malloc(sizeof(nodo_rotate));
           
           ///TODO: Levantar los numeros
           //puse 80 por poner, este no es tipo numero
           nodo_nuevo->a = angulo;
           
           
                      
           //Creo el nodo generico
           crearNodoGenerico( ROTATE , nodo_nuevo);
           
           //Falta grafico, pues es recursivo
           falta_g=1;
}

void f_repeat(int n, int par1_e, int par1_d, char par1_s, int par2_e, int par2_d, char par2_s){
	
		   nodo_repeat * nodo_nuevo = malloc(sizeof(nodo_repeat));
           
           ///TODO: Levantar los numeros
           nodo_nuevo->n=n;
           setNumero(& nodo_nuevo->dx,par1_e,par1_d,par1_s);
           setNumero(& nodo_nuevo->dy,par2_e,par2_d,par2_s);
                      
           //Creo el nodo generico
           crearNodoGenerico( REPEAT , nodo_nuevo);
           
           //Falta grafico, pues es recursivo
           falta_g=1;
}


void agregarNodoParentesis( int tipo){
			//Creo nodo generico del parentesis
		   crearNodoGenerico( tipo , NULL); 
        
			//prueba de parentesis
			parentesis++;
		
           
           //Falta grafico, pues es recursivo
           falta_g=1;	
}

%}

/* Esto indica a Flex que lea sólo un fichero de entrada */
%option noyywrap

%%
    /*** Sección de reglas ***/

    

"circle "[0-9]+  {
           //Creo el nodo particular de circulo
           nodo_circle * nodo_nuevo = malloc(sizeof(nodo_circle));
           
           ///TODO: Levantar el numero, no tengo idea como hacerlo
           //puse 3 por poner alguno
           setNumero(& nodo_nuevo->r,3,0,0);
           
           crearNodoGenerico( CIRCLE , nodo_nuevo);
      
           //NO Falta grafico, pues es NO recursivo
           falta_g=0;
        }
        
"box "[0-9]+.[0-9]+ {
		//Creo el nodo particular de circulo
           nodo_box * nodo_nuevo = malloc(sizeof(nodo_box));
           
           ///TODO: Levantar los numeros
           //puse 1 por poner alguno
           setNumero(& nodo_nuevo->ancho,1,0,0);
           setNumero(& nodo_nuevo->alto,1,0,0);
                      
           //Creo el nodo generico
           crearNodoGenerico( BOX , nodo_nuevo);

			//NO Falta grafico, pues es NO recursivo
           falta_g=0;
}        


"move "[0-9]+.[0-9]+."(" { f_move(1,2,0,1,3,0); agregarNodoParentesis( PARENTESIS_A ); }
"move "[0-9]+.[0-9]+ {	 f_move(1,2,0,1,3,0);}

"scale "[0-9]+.[0-9]+."(" { f_scale(1,2,0,1,3,0);  agregarNodoParentesis( PARENTESIS_A ); }
"scale "[0-9]+.[0-9]+ { f_scale(1,2,0,1,3,0); }

"rotate "[0-9]+."(" { f_rotate(45); agregarNodoParentesis( PARENTESIS_A ); }
"rotate "[0-9]+ { f_rotate(45); }

"repeat "[0-9]+.[0-9]+.[0-9]+."(" { f_repeat(10,1,2,0,1,3,0); agregarNodoParentesis( PARENTESIS_A );}
"repeat "[0-9]+.[0-9]+.[0-9]+ { f_repeat(10,1,2,0,1,3,0); }




"fin" {
	yyterminate();
	}


")" {
	
	parentesis--;
	if (parentesis<0){
			error=1;
			yyterminate();
	}else{
		crearNodoGenerico( PARENTESIS_C , NULL );
	}
	
}


["\n"]* {}	

[" "]* {}	

.       {   
			
			error=1;
			yyterminate();
			
}

%%
/*** Sección de código en C ***/

int main(void)
{
	//No hay error
	error =0;
	
	//no falta grafico
	falta_g=0;
	
	nodo_generico algo;
	algo.sig= NULL;
	algo.ant= NULL;
	algo.adentro= NULL;
	primero= &algo;
	ultimo=primero;
	
	parentesis = 0;
	
    /* Ejecuta el ''lexer'', y después termina. */
    yylex();
    
    if( !error && !falta_g  && (parentesis==0))   imprimir(primero);
    else printf("\n \n ERROR: NO VALIDO \n \n"   );
    
    //destruirArbol();
    

    return 0;
}

